#version 450

layout(location=0)      in vec3 a_Pos;
layout(location=1)      in vec3 a_Normal;
layout(location=2)      in vec3 a_Color;
layout(location=3)      in vec2 a_Texcoord;
layout(location=4)      in vec4 a_Tangent;
layout(location=5)      in vec4 a_Joint;
layout(location=6)      in vec4 a_Weight;

layout(set=0, binding=0, std140) uniform GlobalUbo{
    mat4 projMat;
    mat4 viewMat;
    vec4 viewPos;
    vec4 lightPos;
} globalUbo;

layout(set=0, binding=1, std140) uniform InstanceUbo{
    mat4 modelMat;
} instanceUbo;

layout(set=2, binding=0, std140) buffer Joints{
    mat4 joints[];
};

out gl_PerVertex{
    vec4 gl_Position;
};

layout(location=0) out vec3 v_LightDir;
layout(location=1) out vec3 v_Color;
layout(location=2) out vec2 v_Texcoord;
layout(location=3) out vec3 v_FragPos;
layout(location=4) out vec3 v_ViewPos;
layout(location=5) out vec3 v_Normal;
layout(location=6) out vec3 v_NormalTS;
layout(location=7) out vec3 v_TangentTS;
layout(location=8) out vec3 v_BitangentTS;

void main(){
    mat4 world = instanceUbo.modelMat;
    if (joints.length() > 1) {
        mat4 skinMat = joints[int(a_Joint.x)] * a_Weight.x +
                       joints[int(a_Joint.y)] * a_Weight.y +
                       joints[int(a_Joint.z)] * a_Weight.z +
                       joints[int(a_Joint.w)] * a_Weight.w;
        world = skinMat;
    }
    vec4 worldPos = vec4(world * vec4(a_Pos.x, a_Pos.y, a_Pos.z, 1.f));
    gl_Position = globalUbo.projMat * globalUbo.viewMat * worldPos;
    v_Color = a_Color;
    v_Texcoord = a_Texcoord;

    vec3 lightDir = globalUbo.lightPos.w == 0.0 ? globalUbo.lightPos.xyz : globalUbo.lightPos.xyz - worldPos.xyz;
    v_LightDir = lightDir;
    v_FragPos = worldPos.xyz;
    v_ViewPos = globalUbo.viewPos.xyz;

    mat3 normalMat = mat3(transpose(inverse(world)));
    v_Normal = normalMat * a_Normal;
    v_NormalTS = (world * vec4(a_Normal, 0.0)).xyz;
    v_TangentTS = (world * vec4(a_Tangent.xyz, 0.0)).xyz;
    v_BitangentTS = cross(v_NormalTS, v_TangentTS) * a_Tangent.w;
}